﻿using System;
using Myotragus.Data.Containers;
using Myotragus.Data.Criteria;
using Myotragus.Data.Domain;

namespace Myotragus.Data.Repositories
{
	public class ReadRepository<TEntity> : Repository<TEntity>, IReadRepository<TEntity>
		where TEntity : class, IEntity
	{
		public ReadRepository(IEntitiesContainer entities, IReadQueryBuilder queryBuilder)
			: base(entities)
		{
			if (queryBuilder == null)
				throw new ArgumentNullException();

			QueryBuilder = queryBuilder;
		}

		protected IReadQueryBuilder QueryBuilder { get; private set; }

		public IPagedQuery<TEntity> FindAll()
		{
			return QueryBuilder.CreateQuery<TEntity>(
				QueryBuilder.CreateCriteria(EntityImplementation));
		}

		public int CountAll()
		{
			return QueryBuilder.Count(QueryBuilder.CreateCriteria(EntityImplementation));
		}

		public IPagedQuery<TEntity> FindMatching(object pattern)
		{
			return QueryBuilder.CreateQuery<TEntity>(
				QueryBuilder.CreateMatchingCriteria(EntityImplementation, pattern));
		}

		public int CountMatching(object pattern)
		{
			return QueryBuilder.Count(
				QueryBuilder.CreateMatchingCriteria(EntityImplementation, pattern));
		}

		public IPagedQuery<TEntity> FindLike(object pattern)
		{
			return QueryBuilder.CreateQuery<TEntity>(
				QueryBuilder.CreateLikeCriteria(EntityImplementation, pattern));
		}

		public int CountLike(object pattern)
		{
			return QueryBuilder.Count(
				QueryBuilder.CreateLikeCriteria(EntityImplementation, pattern));
		}
	}

	public class ReadRepository<TEntity, TId> : ReadRepository<TEntity>, IReadRepository<TEntity, TId>
		where TEntity : class, IEntity<TId>
	{
		public ReadRepository(IEntitiesContainer entities, IReadQueryBuilder queryBuilder)
			: base(entities, queryBuilder)
		{
		}

		public virtual TEntity FindById(TId id)
		{
			return (TEntity)QueryBuilder.FindById(EntityImplementation, id);
		}

		public bool Exists(TId id)
		{
			return QueryBuilder.Exists(EntityImplementation, id);
		}
	}
}